package com.shenchuangit.rydemo.web.leaveappr.service.impl;

import com.ruoyi.activiti.domain.dto.HistoryDataDTO;
import com.ruoyi.activiti.domain.dto.HistoryFormDataDTO;
import com.ruoyi.activiti.enumation.BusinessStatusEnum;
import com.ruoyi.activiti.utils.WorkflowHelper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.processSchedule.service.IProcessScheduleDetailService;
import com.shenchuangit.rydemo.web.leaveappr.domain.LeaveApplication;
import com.shenchuangit.rydemo.web.leaveappr.mapper.LeaveApplicationMapper;
import com.shenchuangit.rydemo.web.leaveappr.service.ILeaveApplicationService;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.engine.HistoryService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 请假申请Service业务层处理
 *
 * @author liuyu
 * @date 2022-01-07
 */
@Service
public class LeaveApplicationServiceImpl implements ILeaveApplicationService {
    @Autowired
    private LeaveApplicationMapper leaveApplicationMapper;
    @Autowired
    private WorkflowHelper workflowHelper;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IProcessScheduleDetailService iProcessScheduleDetailService;

    public static final String PROCESS_DEFINITION_KEY = "leave_application";


    /**
     * 查询请假申请
     *
     * @param id 请假申请ID
     * @return 请假申请
     */
    @Override
    public LeaveApplication selectLeaveApplicationById(Long id) {
        LeaveApplication leaveApplication = leaveApplicationMapper.selectLeaveApplicationById(id);
        //给业务实体taskId赋值
        Task task = this.workflowHelper.getNewestTask(leaveApplication.getInstanceId());
        if (null != task) {
            leaveApplication.setTaskId(task.getId());
        }
        return leaveApplication;
    }

    /**
     * 查询请假申请列表
     *
     * @param leaveApplication 请假申请
     * @return 请假申请
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "ur")
    public List<LeaveApplication> selectLeaveApplicationList(LeaveApplication leaveApplication) {
        return leaveApplicationMapper.selectLeaveApplicationList(leaveApplication);
    }

    /**
     * 新增请假申请
     *
     * @param leaveApplication 请假申请
     * @return 结果
     */
    @Override
    public int insertLeaveApplication(LeaveApplication leaveApplication) {
        leaveApplication.setCreateTime(DateUtils.getNowDate());

        //权限相关字段赋值
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        leaveApplication.setCreateBy(loginUser.getUserName());
        leaveApplication.setAclCreateById(loginUser.getUserId());
        leaveApplication.setAclDeptId(loginUser.getDeptId());

        return leaveApplicationMapper.insertLeaveApplication(leaveApplication);
    }

    /**
     * 修改请假申请
     *
     * @param leaveApplication 请假申请
     * @return 结果
     */
    @Override
    public int updateLeaveApplication(LeaveApplication leaveApplication) {
        leaveApplication.setUpdateTime(DateUtils.getNowDate());

        //权限相关字段赋值
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        leaveApplication.setUpdateBy(loginUser.getUserName());

        return leaveApplicationMapper.updateLeaveApplication(leaveApplication);
    }

    /**
     * 批量删除请假申请
     *
     * @param ids 需要删除的请假申请ID
     * @return 结果
     */
    @Override
    public int deleteLeaveApplicationByIds(Long[] ids) {
        return leaveApplicationMapper.deleteLeaveApplicationByIds(ids);
    }

    /**
     * 删除请假申请信息
     *
     * @param id 请假申请ID
     * @return 结果
     */
    @Override
    public int deleteLeaveApplicationById(Long id) {
        return leaveApplicationMapper.deleteLeaveApplicationById(id);
    }

    @Override
    public LeaveApplication selectByInstanceId(String instanceId) {
        LeaveApplication searchParam = new LeaveApplication();
        searchParam.setInstanceId(instanceId);
        List<LeaveApplication> list = this.selectLeaveApplicationList(searchParam);
        if (CollectionUtils.isEmpty(list)) {
            return new LeaveApplication();
        } else if (list.size() == 1) {
            return list.get(0);
        } else {
            throw new CustomException("同一流程实例不能对应多个业务");
        }
    }

    /**
     * 获取带有审批意见的业务信息
     *
     * @param historicTaskInstancePage 当前审批用户的已办理历史
     * @return 业务数据
     */
    @Override
    public List<LeaveApplication> selectByHistoricTaskInstancePage(Page<HistoricTaskInstance> historicTaskInstancePage) {
        List<LeaveApplication> list = new ArrayList<>();
        // 构造按照完成时间排序并且instanceId分组map，key中的list用于判断是在当前用户任务下第几次执行
        Map<String, List<HistoricTaskInstance>> historicTaskGroupCollect = historicTaskInstancePage.getContent().stream()
                .sorted(Comparator.comparing(HistoricTaskInstance::getEndTime))
                .collect(Collectors.groupingBy(HistoricTaskInstance::getProcessInstanceId));
        for (HistoricTaskInstance historicTaskInstance : historicTaskInstancePage.getContent()) {
            HistoricProcessInstance historicProcessInstance = this.historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult();
            //获取审批意见List
            List<HistoryDataDTO> historyDataDTO = this.workflowHelper.getHistoryDataDTO(historicTaskInstance, historicProcessInstance);
            // 获取对应第index次审批的审批意见的大小
            int currentIndex = historicTaskGroupCollect.get(historicTaskInstance.getProcessInstanceId()).indexOf(historicTaskInstance);
            //截取businessKey
            String businessKey = historicProcessInstance.getBusinessKey();
            businessKey = businessKey.replaceAll(PROCESS_DEFINITION_KEY + "#", "");
            //根据业务id获取当前业务信息
            LeaveApplication base = this.selectLeaveApplicationById(Long.parseLong(businessKey));
            //将审批意见添加到业务申报表中
            if (null != historyDataDTO && historyDataDTO.size() > 0) {
                HistoryDataDTO currentHistoryDataDTO = historyDataDTO.get(0);
                List<HistoryFormDataDTO> currentHistoryFormList = new ArrayList<>(2);
                // 放置对应审批意见
                currentHistoryFormList.add(currentHistoryDataDTO.getFormHistoryDataDTO().get((currentIndex+1)*2-2));
                currentHistoryFormList.add(currentHistoryDataDTO.getFormHistoryDataDTO().get((currentIndex+1)*2-1));
                currentHistoryDataDTO.setFormHistoryDataDTO(currentHistoryFormList);
                base.setHistoryDataDTO(currentHistoryDataDTO);
                list.add(base);
            }
        }
        return list.stream().sorted((x, y) -> y.getHistoryDataDTO().getCreatedDate().compareTo(x.getHistoryDataDTO().getCreatedDate())).collect(Collectors.toList());
    }

    /**
     * 提交
     * @param entity 业务主体
     * @return 返回信息
     */
    public int submit(LeaveApplication entity) {
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        //如果instanceId有值，为重新调整
        if (StringUtils.isNotBlank(entity.getInstanceId())) {
            Task task = this.workflowHelper.getNewestTask(entity.getInstanceId());
            if (null != task) {
                entity.setTaskId(task.getId());
            }
            int result = this.workflowHelper.readjust(entity.getTaskId());
            if (result > 0) {
                entity.setStatus(BusinessStatusEnum.REVIEW.toString());
                // 配置流程图变为提交
                iProcessScheduleDetailService.insertProcessScheduleDetail(String.valueOf(entity.getId()), PROCESS_DEFINITION_KEY, "submit", loginUser.getNickName());
                return this.updateLeaveApplication(entity);
            } else {
                return 0;
            }
        } else {
            //先新增或者修改业务
            int insertedRow = 0;
            if (null == entity.getId()) {
                insertedRow = this.insertLeaveApplication(entity);
            } else {
                insertedRow = this.updateLeaveApplication(entity);
            }

            if (insertedRow > 0) {
                //启动流程
                Map<String, Object> variables = new HashMap<>();

                ProcessInstance processInstance = this.workflowHelper.start(PROCESS_DEFINITION_KEY, entity, String.valueOf(entity.getId()), variables);

                //回写工作流信息
                entity.setStatus(BusinessStatusEnum.REVIEW.toString());
                // 配置流程图变为提交
                iProcessScheduleDetailService.insertProcessScheduleDetail(String.valueOf(entity.getId()), PROCESS_DEFINITION_KEY, "submit", loginUser.getNickName());
                entity.setInstanceId(processInstance.getId());
                leaveApplicationMapper.updateLeaveApplication(entity);
                return 1;
            } else {
                return 0;
            }

        }
    }
}
